/* Copyright 2009 Requirements Management System 
 * 
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.mags.remas.editfile;

import java.io.ByteArrayInputStream; 
import java.io.ByteArrayOutputStream;  
import java.math.BigDecimal;
import java.sql.Blob;
import java.util.List;

import org.eclipse.swt.SWT;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.events.SelectionListener;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.graphics.ImageData;
import org.eclipse.swt.graphics.ImageLoader;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.FileDialog;
import org.eclipse.swt.widgets.ToolBar;
import org.eclipse.swt.widgets.ToolItem;
import org.eclipse.ui.IEditorInput;
import org.mags.common.EngineContext;
import org.mags.remas.logic.EntityFileUtils;
import org.mags.remas.logic.EntityLogic;
import org.mags.remas.model.entity.EntityFile;
import org.mags.remas.model.entity.KeyDefinition;
import org.mags.remas.model.entity.KeyValue;
import org.mags.remas.view.commons.ImageProvider;
import org.mags.remas.view.commons.RelationshipEditorBase;
import org.mags.remas.view.widgets.ImageCanvas;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.support.TransactionCallbackWithoutResult;

/**
 * 
 * @author Mario Gaitan
 *
 */
public class ImageEditor extends RelationshipEditorBase {
	public static final String ID = "org.mags.remas.editfile.imageEditor";
	private ImageCanvas imageCanvas;
	private EntityFile entityFile;
	private String currentDir="";
	private static final String WIDTH_KEY = "Width";
	private static final String HEIGHT_KEY = "Height";
	
	public void openFile() {
		FileDialog fileChooser = new FileDialog(imageCanvas.getShell(), SWT.OPEN);
		fileChooser.setText("Open image file");
		fileChooser.setFilterPath(currentDir);
		fileChooser.setFilterExtensions(new String[] { "*.gif; *.jpg; *.png; *.ico; *.bmp" });
		fileChooser.setFilterNames(new String[] { "image" + " (gif, jpeg, png, ico, bmp)" });
		String filename = fileChooser.open();
		if (filename != null){
			imageCanvas.loadImage(filename);
			currentDir = fileChooser.getFilterPath();
		}
	}
	protected Image getImage() {
		if(imageCanvas.getSourceImage()==null)
			return null;
		Image image = imageCanvas.getImage();
		if(imageCanvas.getRotateFactor()>0)
			image = imageCanvas.rotate(imageCanvas.getRotateFactor(), image);
		else 
			image = new Image(getSite().getShell().getDisplay(), (ImageData)image.getImageData().clone());
		return image;
	}
	public void save() {
		if(imageCanvas.getSourceImage()!=null) {
			if(entityFile==null)
				entityFile = new EntityFile();		
			entityFile.setEntity(entityRelationship.getEntity());
			entityFile.setExtension("jpeg");
			ImageLoader loader = new ImageLoader();
			//TODO: TEMPORAL
			Image image = imageCanvas.getImage();
			int width = image.getBounds().width;
			int height = image.getBounds().height;
			width = (int)(width * imageCanvas.getZoomFactor());
			height = (int)(height * imageCanvas.getZoomFactor());
			final KeyValue _width = entityRelationship.getEntity().getKeyValue(WIDTH_KEY)!=null?(KeyValue)entityRelationship.getEntity().getKeyValue(WIDTH_KEY):new KeyValue();
			final KeyValue _height = entityRelationship.getEntity().getKeyValue(HEIGHT_KEY)!=null?(KeyValue)entityRelationship.getEntity().getKeyValue(HEIGHT_KEY):new KeyValue();
			final boolean[] saveKeys = new boolean[1];
			saveKeys[0] = true;
			if(_width.getKeyValueId()==0) {
				KeyDefinition keyDefinition = EngineContext.getDataContext().getEntityProviderFactory().getKeyDefinitionProvider().getByName(WIDTH_KEY);
				if(keyDefinition==null)
					saveKeys[0] = false;
				_width.setEntityId(entityRelationship.getEntity().getEntityId());
				_width.setKeyDefinition(keyDefinition);
			}
			if(_height.getKeyValueId()==0) {
				KeyDefinition keyDefinition = EngineContext.getDataContext().getEntityProviderFactory().getKeyDefinitionProvider().getByName(HEIGHT_KEY);
				if(keyDefinition==null)
					saveKeys[0] = false;
				_height.setEntityId(entityRelationship.getEntity().getEntityId());
				_height.setKeyDefinition(keyDefinition);
			}			
			_width.setNumericValue(new BigDecimal(width));
			_height.setNumericValue(new BigDecimal(height));
			boolean dispose = false;
			if(imageCanvas.getRotateFactor()>0) {
				image = imageCanvas.rotate(imageCanvas.getRotateFactor(), image);
				dispose = true;
			}
			loader.data = new ImageData[]{image.getImageData()};
			ByteArrayOutputStream out = new ByteArrayOutputStream();
			loader.save(out, SWT.IMAGE_JPEG);
			if(dispose)
				image.dispose();
			Blob blob = EngineContext.getDataContext().getEntityProviderFactory().getEntityFileProvider().getDao().createBlob(out.toByteArray());
			entityFile.setContent(blob);
			entityFile.setExtension("jpeg");
			EngineContext.getDataContext().getTransactionTemplate().execute(new TransactionCallbackWithoutResult() {
				@Override
				protected void doInTransactionWithoutResult(
						TransactionStatus status) {
					EngineContext.getDataContext().getEntityProviderFactory().getEntityFileProvider().createOrUpdate(entityFile);
					if(saveKeys[0]) {
						EngineContext.getDataContext().getEntityProviderFactory().getKeyValueProvider().createOrUpdate(_width);
						EngineContext.getDataContext().getEntityProviderFactory().getKeyValueProvider().createOrUpdate(_height);
					}
				}
			});

		}
	}
	@Override
	public void dispose() {
		super.dispose();
		imageCanvas.dispose();
	}
	@Override
	public void createPartControl(Composite parent) {
		GridLayout gridLayout = new GridLayout(1, true);
		gridLayout.marginHeight = 0;
		gridLayout.marginWidth = 0;
		gridLayout.verticalSpacing = 0;
		gridLayout.horizontalSpacing = 0;		
		parent.setLayout(gridLayout);		
		createToolBar(parent);
		createImageCanvas(parent);
		EntityLogic.getInstance().loadKeys(entityRelationship);		
		loadImage();
		calculeZoom();
	}
	private void calculeZoom() {
		if(imageCanvas.getImage()!=null) {
			if(entityRelationship.getEntity().getKeyValue(WIDTH_KEY)!=null
			&& entityRelationship.getEntity().getKeyValue(HEIGHT_KEY)!=null) {
				BigDecimal _width = entityRelationship.getEntity().getKeyValue(WIDTH_KEY).getNumericValue();
				BigDecimal _height = entityRelationship.getEntity().getKeyValue(HEIGHT_KEY).getNumericValue();
				if(_width!=null&&_height!=null) {
					double width = _width.doubleValue();
					double height = _height.doubleValue();
					int currentWidth = imageCanvas.getImage().getBounds().width;
					int currentHeight = imageCanvas.getImage().getBounds().height;
					width = width / currentWidth;
					height = height / currentHeight;
					if(width>=0.1&&width<=2.0&&height>=0.1&&height<=2.0) {
						imageCanvas.setZoomFactor((float)width);
						imageCanvas.updateImage();
					}
				}
			}
		}
	}
	public void refresh() {
		if(imageCanvas.getSourceImage()!=null) {
			imageCanvas.disposeImages();
			imageCanvas.redraw();
			loadImage();
		}
	}
	protected void createImageCanvas(Composite parent) {
		GridData gridData = new GridData();
		gridData.horizontalAlignment = SWT.FILL;
		gridData.grabExcessHorizontalSpace = true;
		gridData.verticalAlignment = SWT.FILL;	
		gridData.grabExcessVerticalSpace=true;		
		imageCanvas=new ImageCanvas(parent);
		imageCanvas.setLayoutData(gridData);
	}
	protected void createToolBar(Composite parent) {
		ToolBar toolBar = new ToolBar(parent, SWT.FLAT);
		GridData gridData = new GridData();
		gridData.horizontalAlignment = SWT.RIGHT;
		gridData.grabExcessHorizontalSpace = true;		
		toolBar.setLayoutData(gridData);

		ToolItem refreshButton = new ToolItem(toolBar, SWT.NONE);
		refreshButton.setText("refresh");
		refreshButton.setImage(ImageProvider.getCommonImage("refresh.png"));
		refreshButton.addSelectionListener(new SelectionListener() {
			public void widgetDefaultSelected(SelectionEvent e) {
			}
			public void widgetSelected(SelectionEvent e) {
				try {
					refresh();
				} catch(Exception _e) {
					exceptionCatched(_e);
				}
			}
		});		

		/*
		ToolItem measureButton = new ToolItem(toolBar, SWT.NONE);
		measureButton.setText("measure");
		measureButton.setImage(ImageProvider.getCommonImage("measure.png"));
		measureButton.addSelectionListener(new SelectionListener() {
			public void widgetDefaultSelected(SelectionEvent e) {
			}
			public void widgetSelected(SelectionEvent e) {
				if(imageCanvas.isCropMode())
					imageCanvas.setCropMode(false);
				else
					imageCanvas.setCropMode(true);
			}
		});		

		ToolItem cropButton = new ToolItem(toolBar, SWT.NONE);
		cropButton.setText("crop");
		cropButton.setImage(ImageProvider.getCommonImage("crop.png"));
		cropButton.addSelectionListener(new SelectionListener() {
			public void widgetDefaultSelected(SelectionEvent e) {
			}
			public void widgetSelected(SelectionEvent e) {
				if(imageCanvas.isCropMode())
					imageCanvas.crop();
			}
		});		
		*/
		
		ToolItem rotateButton = new ToolItem(toolBar, SWT.NONE);
		rotateButton.setText("rotate");
		rotateButton.setImage(ImageProvider.getCommonImage("rotate.png"));
		rotateButton.addSelectionListener(new SelectionListener() {
			public void widgetDefaultSelected(SelectionEvent e) {
			}
			public void widgetSelected(SelectionEvent e) {
				try {
					if(imageCanvas.getSourceImage()!=null)
						imageCanvas.rotate();
				} catch(Exception _e) {
					exceptionCatched(_e);
				}
			}
		});				
		
		ToolItem fitButton = new ToolItem(toolBar, SWT.NONE);
		fitButton.setText("fit");
		fitButton.setImage(ImageProvider.getCommonImage("fit.png"));
		fitButton.addSelectionListener(new SelectionListener() {
			public void widgetDefaultSelected(SelectionEvent e) {
			}
			public void widgetSelected(SelectionEvent e) {
				try {
					if(imageCanvas.getSourceImage()!=null)
						imageCanvas.fit();
				} catch(Exception _e) {
					exceptionCatched(_e);
				}
			}
		});		

		
		ToolItem zoomOutButton = new ToolItem(toolBar, SWT.NONE);
		zoomOutButton.setText("zoom out");
		zoomOutButton.setImage(ImageProvider.getCommonImage("zoomout.png"));
		zoomOutButton.addSelectionListener(new SelectionListener() {
			public void widgetDefaultSelected(SelectionEvent e) {
			}
			public void widgetSelected(SelectionEvent e) {
				try {
					if(imageCanvas.getSourceImage()!=null)	
						imageCanvas.zoomOut();
				} catch(Exception _e) {
					exceptionCatched(_e);
				}
			}
		});		

		
		ToolItem zoomInButton = new ToolItem(toolBar, SWT.NONE);
		zoomInButton.setText("zoom in");
		zoomInButton.setImage(ImageProvider.getCommonImage("zoomin.png"));
		zoomInButton.addSelectionListener(new SelectionListener() {
			public void widgetDefaultSelected(SelectionEvent e) {
			}
			public void widgetSelected(SelectionEvent e) {
				try {
					if(imageCanvas.getSourceImage()!=null)
						imageCanvas.zoomIn();
				} catch(Exception _e) {
					exceptionCatched(_e);
				}
			}
		});		
		
		ToolItem openButton = new ToolItem(toolBar, SWT.NONE);
		openButton.setText("load");
		openButton.setImage(ImageProvider.getCommonImage("load.png"));
		openButton.addSelectionListener(new SelectionListener() {
			public void widgetDefaultSelected(SelectionEvent e) {
			}
			public void widgetSelected(SelectionEvent e) {
				try {
					openFile();
				} catch(Exception _e) {
					exceptionCatched(_e);
				}
			}
		});		
		ToolItem saveButton = new ToolItem(toolBar, SWT.NONE);
		saveButton.setText("save");
		saveButton.setImage(ImageProvider.getCommonImage("save.png"));
		saveButton.addSelectionListener(new SelectionListener() {
			public void widgetDefaultSelected(SelectionEvent e) {
			}
			public void widgetSelected(SelectionEvent e) {
				try {
					save();
				} catch(Exception _e) {
					exceptionCatched(_e);
				}
			}
		});				
	}
	private void loadImage() {
		List<EntityFile> files = EntityFileUtils.getFiles(entityRelationship.getEntity().getEntityId());
		if(files.size()>0) {
			entityFile = files.get(0);
			imageCanvas.loadImage(new ByteArrayInputStream(entityFile.getRawContent()));
		} else {
			entityFile = new EntityFile();
			entityFile.setEntity(entityRelationship.getEntity());
		}
	}
	@Override
	public void init(IEditorInput input) {
	}
	@Override
	public boolean ignoreException(Exception e) {
		return false;
	}
	@Override
	public void setFocus() {
		imageCanvas.setFocus();
	}	
}
